/*
Copyright (C) 2010 Ronie Salgado

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "stdafx.h"
#include "QProcessWindow.h"
#include "QooleId.h"

BEGIN_EVENT_TABLE(QProcessWindow, wxRichTextCtrl)
	EVT_IDLE(QProcessWindow::OnIdle)
	EVT_END_PROCESS(QID_PROCESS, QProcessWindow::OnFinishProcess)
END_EVENT_TABLE()

QProcessWindow::QProcessWindow(wxWindow *parent)
	: wxRichTextCtrl(parent, QID_PROCESS_WINDOW, wxEmptyString, wxDefaultPosition,
			wxSize(400,200))
{
	currentProcess = NULL;

	SetEditable(false);
}

QProcessWindow::~QProcessWindow()
{
}

void QProcessWindow::ClearWindow(void)
{
	Clear();
}

void QProcessWindow::OutputText(const wxChar *text)
{
	AppendText(text);
}

void QProcessWindow::GetViewPos()
{
}

void QProcessWindow::SetViewPos()
{
	ShowPosition(GetLastPosition());
}

bool QProcessWindow::IsProcessRunning()
{
	return currentProcess != NULL;
}

void QProcessWindow::ExecProcess(const wxString &commandLine, const wxString &workDir,
			FinishCallback callback)
{
	ASSERT(currentProcess == NULL);

	// Store the callback.
	currentCallback = callback;

	// Create the process.
	currentProcess = new wxProcess(this, QID_PROCESS);

	// Redirect I/O
	currentProcess->Redirect();

	// Store the old working dir.
	wxString oldDir = wxGetCwd();

	// Change the working dir.
	wxSetWorkingDirectory(workDir);

	// Execute the process.
	long pid = wxExecute(commandLine, wxEXEC_ASYNC, currentProcess);

	// Restore the old working dir.
	wxSetWorkingDirectory(oldDir);

	// Check for errors.
	if(pid == 0)
	{
		AppendText(wxString::Format(_("Failed to run: %s\n"), commandLine.c_str()));
		delete currentProcess;
		currentProcess = NULL;
	}
}

void QProcessWindow::TerminateProcess()
{
}

void QProcessWindow::OnIdle(wxIdleEvent &event)
{
	if(!currentProcess)
		return;

	// Read stdout.
	char buffer[256];
	wxInputStream *pstdout = currentProcess->GetInputStream();
	while(currentProcess->IsInputAvailable())
	{
		pstdout->Read(buffer, 255);
		size_t amount = pstdout->LastRead();
		if(amount == 0)
			break;
		buffer[amount] = 0;
		AppendText(wxString(buffer, wxConvUTF8));
	}

	// Read stderr.
	wxInputStream *pstderr = currentProcess->GetErrorStream();
	while(currentProcess->IsErrorAvailable())
	{
		pstderr->Read(buffer, 255);
		size_t amount = pstderr->LastRead();
		if(amount == 0)
			break;
		buffer[amount] = 0;
		AppendText(wxString(buffer, wxConvUTF8));
	}

	SetViewPos();

	// Keep processing idle events.
	event.RequestMore();
}

void QProcessWindow::OnFinishProcess(wxProcessEvent &event)
{
	// Read more data.
	wxIdleEvent ev;
	OnIdle(ev);

	// Delete the process.
	delete currentProcess;
	currentProcess = NULL;

	// Perform the call back.
	if(currentCallback)
	{
		FinishCallback callback = currentCallback;
		currentCallback = NULL;
		callback();
	}
}

